package com.ocean.web.util.rwdata;

import com.ocean.system.domain.SeaTempNcMetadata;
import ucar.ma2.Array;
import ucar.nc2.Attribute;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 智能网格海温 NC 文件元数据读取工具（适配 netcdfAll-5.4.1 + NMF_BEN_OSM_CSDT 格式）
 * 要素名称elements返回短名称（分号隔开），沿用 SeaTempNcMetadata 实体类
 */
public class GlobalZnwgSstNcReader_5_4_1 {

    // 时间格式工具（UTC+8 中国标准时间，适配国内智能网格数据）
    private static final SimpleDateFormat CMA_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat FILENAME_TIME_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
    static {
        CMA_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        FILENAME_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+8"));
    }

    // 智能网格文件名正则表达式（匹配：202509090800 起报时间，120001 预报时效）
    private static final Pattern FILENAME_PATTERN = Pattern.compile(
            "^NMF_BEN_OSM_CSDT_(\\d{12})_(\\d{6})_SST_(\\d{2})_L0\\.nc$"
    );

    /**
     * 核心方法：读取智能网格海温 NC 文件元数据，返回 SeaTempNcMetadata 实体
     * @param ncFilePath NC 文件路径（本地文件）
     * @return SeaTempNcMetadata 元数据实体（要素为短名称）
     * @throws IOException NC 文件读取异常
     */
    public SeaTempNcMetadata readSmartGridMetadata(String ncFilePath) throws IOException {
        // 前置校验：路径非空+文件存在
        if (ncFilePath == null || ncFilePath.trim().isEmpty()) {
            throw new IllegalArgumentException("NC文件路径不能为空！");
        }
        File ncFile = new File(ncFilePath);
        if (!ncFile.exists() || !ncFile.isFile()) {
            throw new IOException("NC文件不存在或非法：" + ncFilePath);
        }

        // 提取文件名（用于解析和赋值）
        String ncFileName = extractFileName(ncFilePath);

        // 从文件名解析关键信息（起报时间、预报时效）
        FileNameParseResult parseResult = parseFileName(ncFileName);

        try (NetcdfFile ncFileObj = NetcdfFile.open(ncFilePath)) {
            // 1. NC文件名（已提取）
            // 2. 来源（优先读NC文件 institution/source 属性，默认中国气象局智能网格）
            String source = getAttrValue(ncFileObj, "institution", "中国气象局智能网格预报系统");
            if ("中国气象局智能网格预报系统".equals(source)) {
                source = getAttrValue(ncFileObj, "source", "中国气象局智能网格预报系统");
            }

            // 3. 类型（固定为智能网格海温）
            String type = "智能网格海表温度（SST）";

            // 4. 起报时间（文件名解析结果优先，失败则读NC文件 base_time 属性）
            String forecastBaseTime = parseResult.getBaseTime();
            if ("解析失败".equals(forecastBaseTime)) {
                forecastBaseTime = parseBaseTimeFromNcFile(ncFileObj);
            }

            // 5. 预报时效（文件名解析结果优先，失败则读NC文件 forecast_length 属性）
            String forecastLeadTime = parseResult.getLeadTime();
            if ("解析失败".equals(forecastLeadTime)) {
                forecastLeadTime = parseLeadTimeFromNcFile(ncFileObj);
            }

            // 6. 预报频次（智能网格默认：每6小时1次，支持从NC文件读取）
            String forecastFreq = getAttrValue(ncFileObj, "forecast_frequency", "每6小时1次（02/08/14/20时起报）");

            // 7. 覆盖范围（从NC文件解析经纬度范围，智能网格通常覆盖中国近海/全球）
            String coverage = parseCoverage(ncFileObj);

            // 8. 空间分辨率（智能网格常见 0.05°×0.05°，优先读NC文件 grid_resolution 属性）
            String spatialRes = getAttrValue(ncFileObj, "grid_resolution", calculateSpatialResolution(ncFileObj));

            // 9. 要素名称elements（短名称，分号隔开）- 核心修改
            String elements = getSeaTempShortNames(ncFileObj);

            // 构建并返回实体
            return new SeaTempNcMetadata(
                    ncFileName,
                    source,
                    type,
                    forecastBaseTime,
                    forecastLeadTime,
                    forecastFreq,
                    coverage,
                    spatialRes,
                    elements
            );
        }
    }

    // ---------------------- 核心新增方法：提取要素短名称（分号隔开）----------------------
    /**
     * 提取智能网格海温要素短名称（纯变量名，分号隔开）
     * 适配：变量名含下划线则取第一部分（如 sst_00 → sst），自动去重
     */
    private String getSeaTempShortNames(NetcdfFile ncFile) {
        // 智能网格海温常见变量名（适配国内数据格式）
        String[] targetVarNames = {"sst", "tos", "sea_surface_temperature", "temperature_at_sea_surface"};
        StringBuilder shortNames = new StringBuilder();

        for (String varName : targetVarNames) {
            Variable var = ncFile.findVariable(varName);
            if (var == null) {
                continue; // 变量不存在则跳过，避免空指针
            }

            // 提取短名称：优先取变量的shortName，无则用变量名
            String shortName = var.getShortName() != null ? var.getShortName() : varName;
            // 处理下划线后缀（如 "sst_00" → "sst"、"sea_surface_temperature_10m" → "sea_surface_temperature"）
            if (shortName.contains("_")) {
                shortName = shortName.split("_")[0].trim();
            }
            // 避免重复添加同一短名称
            if (shortNames.indexOf(shortName) == -1) {
                shortNames.append(shortName).append(";");
            }
        }

        // 移除最后一个分号，为空则返回默认值
        if (shortNames.length() > 0) {
            return shortNames.substring(0, shortNames.length() - 1);
        } else {
            return "未识别到要素短名称";
        }
    }

    // ---------------------- 原有智能网格专属方法（保持不变）----------------------
    /**
     * 从文件路径提取文件名
     */
    private String extractFileName(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return "unknown.nc";
        }
        filePath = filePath.replace("\\", "/");
        int lastSlashIndex = filePath.lastIndexOf("/");
        return lastSlashIndex == -1 ? filePath : filePath.substring(lastSlashIndex + 1);
    }

    /**
     * 解析智能网格文件名：提取起报时间（yyyyMMddHHmm）、预报时效（HHmmss）
     */
    private FileNameParseResult parseFileName(String fileName) {
        Matcher matcher = FILENAME_PATTERN.matcher(fileName);
        if (!matcher.matches()) {
            return new FileNameParseResult("解析失败", "解析失败");
        }

        try {
            // 解析起报时间（文件名第3段：202509090800 → 2025-09-09 08:00:00）
            String baseTimeStr = matcher.group(1);
            Date baseTime = FILENAME_TIME_FORMAT.parse(baseTimeStr);
            String formattedBaseTime = CMA_TIME_FORMAT.format(baseTime);

            // 解析预报时效（文件名第4段：120001 → 120小时01分钟 → 120小时）
            String leadTimeStr = matcher.group(2);
            int hours = Integer.parseInt(leadTimeStr.substring(0, 3)); // 前3位：120
            String formattedLeadTime = hours + "小时";

            return new FileNameParseResult(formattedBaseTime, formattedLeadTime);
        } catch (ParseException | NumberFormatException e) {
            return new FileNameParseResult("解析失败", "解析失败");
        }
    }

    /**
     * 从NC文件读取 base_time 属性（起报时间备用解析）
     */
    private String parseBaseTimeFromNcFile(NetcdfFile ncFile) {
        String baseTimeStr = getAttrValue(ncFile, "base_time", null);
        if (baseTimeStr == null) {
            baseTimeStr = getAttrValue(ncFile, "forecast_reference_time", null);
        }
        if (baseTimeStr == null) {
            return "未知";
        }

        try {
            // 适配NC文件中常见的时间格式（如：2025-09-09 08:00:00 或 202509090800）
            if (baseTimeStr.length() == 12) {
                Date date = FILENAME_TIME_FORMAT.parse(baseTimeStr);
                return CMA_TIME_FORMAT.format(date);
            } else {
                Date date = CMA_TIME_FORMAT.parse(baseTimeStr.trim());
                return CMA_TIME_FORMAT.format(date);
            }
        } catch (ParseException e) {
            return baseTimeStr; // 解析失败返回原始值
        }
    }

    /**
     * 从NC文件读取 forecast_length 属性（预报时效备用解析）
     */
    private String parseLeadTimeFromNcFile(NetcdfFile ncFile) {
        String leadTimeStr = getAttrValue(ncFile, "forecast_length", null);
        if (leadTimeStr == null) {
            leadTimeStr = getAttrValue(ncFile, "lead_time", null);
        }
        if (leadTimeStr == null) {
            return "未知";
        }

        try {
            // 适配数值格式（如：120 → 120小时）
            int leadHours = Integer.parseInt(leadTimeStr);
            return leadHours + "小时";
        } catch (NumberFormatException e) {
            return leadTimeStr; // 非数值格式直接返回
        }
    }

    /**
     * 解析覆盖范围（经纬度范围）
     */
    private String parseCoverage(NetcdfFile ncFile) {
        String latRange = getLatLonRange(ncFile, "lat", "latitude");
        String lonRange = getLatLonRange(ncFile, "lon", "longitude");

        if ("未知".equals(latRange) && "未知".equals(lonRange)) {
            return "中国近海及邻近海域（智能网格默认覆盖范围）";
        }
        return String.format("全球/中国近海（纬度：%s，经度：%s）", latRange, lonRange);
    }

    /**
     * 获取经纬度范围（适配 lat/latitude、lon/longitude 变量名）
     */
    private String getLatLonRange(NetcdfFile ncFile, String varName1, String varName2) {
        Variable var = ncFile.findVariable(varName1);
        if (var == null) {
            var = ncFile.findVariable(varName2);
        }
        if (var == null) {
            return "未知";
        }

        try {
            Array array = var.read();
            double min = array.getDouble(0);
            double max = array.getDouble((int) (array.getSize() - 1));
            // 处理维度递减情况（如纬度从90到-90）
            if (min > max) {
                double temp = min;
                min = max;
                max = temp;
            }
            // 经纬度格式优化（保留2位小数，适配国内数据）
            return String.format("%.2f° - %.2f°", min, max);
        } catch (Exception e) {
            return "解析失败";
        }
    }

    /**
     * 计算空间分辨率（经纬度间隔）
     */
    private String calculateSpatialResolution(NetcdfFile ncFile) {
        String latRes = calculateDimResolution(ncFile, "lat", "latitude");
        String lonRes = calculateDimResolution(ncFile, "lon", "longitude");

        if ("未知".equals(latRes) && "未知".equals(lonRes)) {
            return "0.05°×0.05°（智能网格默认分辨率）";
        }
        return String.format("纬度：%s，经度：%s", latRes, lonRes);
    }

    /**
     * 计算单个维度的分辨率（间隔）
     */
    private String calculateDimResolution(NetcdfFile ncFile, String varName1, String varName2) {
        Variable var = ncFile.findVariable(varName1);
        if (var == null) {
            var = ncFile.findVariable(varName2);
        }
        if (var == null) {
            return "未知";
        }

        try {
            Array array = var.read();
            if (array.getSize() < 2) {
                return "未知";
            }
            // 计算相邻两个格点的间隔（取绝对值）
            double res = Math.abs(array.getDouble(1) - array.getDouble(0));
            return String.format("%.2f°", res);
        } catch (Exception e) {
            return "解析失败";
        }
    }

    /**
     * 通用属性读取方法（支持全局属性和变量属性）
     */
    private String getAttrValue(NetcdfFile ncFile, String attrName, String defaultValue) {
        Attribute attr = ncFile.findGlobalAttribute(attrName);
        return attr != null ? attr.getStringValue().trim() : defaultValue;
    }

    private String getAttrValue(Variable variable, String attrName, String defaultValue) {
        Attribute attr = variable.findAttribute(attrName);
        return attr != null ? attr.getStringValue().trim() : defaultValue;
    }

    /**
     * 内部辅助类：存储文件名解析结果（起报时间、预报时效）
     */
    private static class FileNameParseResult {
        private final String baseTime; // 起报时间
        private final String leadTime; // 预报时效

        public FileNameParseResult(String baseTime, String leadTime) {
            this.baseTime = baseTime;
            this.leadTime = leadTime;
        }

        public String getBaseTime() {
            return baseTime;
        }

        public String getLeadTime() {
            return leadTime;
        }
    }

    // 测试方法（验证短名称输出）
    public static void main(String[] args) {
        // 测试文件路径（替换为你的 NMF_BEN_OSM_CSDT 格式文件路径）
        String ncFilePath = "E:\\项目资料备份\\新云平台文件\\2025工作\\样例数据-检验\\智能网格海温\\NMF_BEN_OSM_CSDT_202509090800_120001_SST_00_L0.nc";
        GlobalZnwgSstNcReader_5_4_1 reader = new GlobalZnwgSstNcReader_5_4_1();

        try {
            SeaTempNcMetadata metadata = reader.readSmartGridMetadata(ncFilePath);
            // 打印结果（沿用实体类的 toString 格式，要素为短名称）
            System.out.println("智能网格海温 NC 文件元数据：");
            System.out.println(metadata);

            // 结构化获取字段示例（要素短名称）
            System.out.println("\n结构化字段获取：");
            System.out.println("起报时间：" + metadata.getForecastBaseTime());
            System.out.println("空间分辨率：" + metadata.getSpatialRes());
            System.out.println("要素名称elements（短名称）：" + metadata.getElements());
        } catch (IOException e) {
            System.err.println("读取失败：" + e.getMessage());
            e.printStackTrace();
        }
    }
}